package br.eng.eliseu.gwt.gestaoWeb.client.ui.core;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import br.eng.eliseu.gwt.gestaoWeb.client.ui.component.SimpleDataGrid;
import br.eng.eliseu.gwt.gestaoWeb.client.ui.component.SimpleDataGrid.GetValue;
import br.eng.eliseu.gwt.gestaoWeb.model.endereco.Endereco;
import br.eng.eliseu.gwt.gestaoWeb.model.endereco.TipoEnderecoEnum;
import br.eng.eliseu.gwt.gestaoWeb.model.pessoa.PessoaEndereco;

import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.text.shared.Renderer;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ValueListBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ProvidesKey;

public class EnderecoListView extends Composite {

	private static EnderecoListViewUiBinder uiBinder = GWT.create(EnderecoListViewUiBinder.class);

	interface EnderecoListViewUiBinder extends UiBinder<Widget, EnderecoListView> {
	}
	@UiField Button novoEnderecoButton;
//	@UiField Button excluiEnderecoButton;

	@UiField AbsolutePanel editEnderecoPanel;
	@UiField Label msgEditLabel;
	@UiField(provided = true) ValueListBox<TipoEnderecoEnum> tipoEnderecoLBox;
	@UiField CheckBox principalCBox;
	@UiField EnderecoView enderecoView;
	@UiField Button salvarEditButton;
	@UiField Button cancelaEditButton;
	@UiField(provided=true) SimpleDataGrid<PessoaEndereco> enderecoDGrid;
	@UiField VerticalPanel enderecoListPanel;

	private final DialogBox dlg = new DialogBox();
//	private FlexTableUtil enderecoFTUtil = new FlexTableUtil();
	
//	private final SingleSelectionModel<PessoaEndereco> selectionModel = new SingleSelectionModel<PessoaEndereco>();
	private List<PessoaEndereco> enderecoList = new ArrayList<PessoaEndereco>();
//	private PessoaEndereco enderecoSelecionado;
	private int indiceEnderecoSelecionado;

//	private Comparator<PessoaEndereco> comparatorPessoaEndereco = new Comparator<PessoaEndereco>() {
//		public int compare(PessoaEndereco a, PessoaEndereco b) {return a.compareTo(b);}};

	public EnderecoListView() {
		criaTabelaEndereco();
		
		// --- Controi ValueListBox <TipoEnderecoEnum>
		tipoEnderecoLBox = new ValueListBox<TipoEnderecoEnum>(new Renderer<TipoEnderecoEnum>() {
			public String render(TipoEnderecoEnum value) {
				String s = "";
				if (value != null) {
					s = value.getNome();
				}
				return s;
			}

			public void render(TipoEnderecoEnum value, Appendable appendable) throws IOException {
				String s = render(value);
				appendable.append(s);
			}
		});

		initWidget(uiBinder.createAndBindUi(this));

		editEnderecoPanel.setVisible(false);
		showMessage(msgEditLabel, "", false);

		bind();
	}

	public void criaTabelaEndereco() {
		ProvidesKey<PessoaEndereco> keyProvider = new ProvidesKey<PessoaEndereco>() {
			public Object getKey(PessoaEndereco item) {
				return (item == null) ? null : item.getId();
			}
		};
		
		enderecoDGrid = new SimpleDataGrid<PessoaEndereco>(keyProvider, false);
//		enderecoDGrid.addColumnCheck();
		enderecoDGrid.addColumnDelete( new FieldUpdater<PessoaEndereco, String>() {
		      public void update(int index, PessoaEndereco object, String value) {
		    	excluiEndereco(object);
		      }
		    });
		enderecoDGrid.addColumnEdit( new FieldUpdater<PessoaEndereco, String>() {
		      public void update(int index, PessoaEndereco object, String value) {
		        editaEndereco(object);
		      }
		    });
		enderecoDGrid.addColumn("Endereco", "5px", new TextCell(), 
				new GetValue<PessoaEndereco, String>() {
					public String getValue(PessoaEndereco obj) {
						if (obj.getTipoEndereco()==null){
							return "";
						}
						return obj.getTipoEndereco().getNome();
					}
				}, null);
		enderecoDGrid.addColumn("Logrradouro", "10px", new TextCell(), 
				new GetValue<PessoaEndereco, String>() {
					public String getValue(PessoaEndereco obj) {
						if (obj.getEndereco()==null){
							return "";
						}
						return obj.getEndereco().getLogradouroX();
					}
				}, null);
		enderecoDGrid.addColumn("Cidade", "7px", new TextCell(), 
				new GetValue<PessoaEndereco, String>() {
					public String getValue(PessoaEndereco obj) {
						if (obj.getEndereco()==null || obj.getEndereco().getCidade()==null){
							return "";
						}
						return obj.getEndereco().getCidade().getNome();
					}
				}, null);
		enderecoDGrid.addColumn("UF", "2px", new TextCell(), 
				new GetValue<PessoaEndereco, String>() {
					public String getValue(PessoaEndereco obj) {
						if (obj.getEndereco()==null || obj.getEndereco().getEstado()==null){
							return "";
						}
						return obj.getEndereco().getEstado().getSigla();
					}
				}, null);
		
	}

	private void bind() {
		populaTipoEnderecoLBox();
	}

	public void populaTipoEnderecoLBox() {
		List<TipoEnderecoEnum> list = new ArrayList<TipoEnderecoEnum>(Arrays.asList(TipoEnderecoEnum.values()));
		tipoEnderecoLBox.setAcceptableValues(list);
	}

	public List<PessoaEndereco> getEnderecoList() {
		return enderecoList;
	}

	public void setEnderecoList(List<PessoaEndereco> enderecoList) {
		this.enderecoList = enderecoList;
		populaEnderecoTabela(enderecoList);
	}

	@UiHandler("novoEnderecoButton")
	void onNovoEnderecoButtonClick(ClickEvent event) {
		limpaEnderecoView();
		if (enderecoList == null) {
			// --- é o primeiro endereco, e ele tem que ser o principal
			principalCBox.setValue(true);
			principalCBox.setEnabled(false);
		}
		indiceEnderecoSelecionado = -1;
		openDlg(editEnderecoPanel, "Novo de Endereço");

	}

//	@UiHandler("excluiEnderecoButton")
//	void onExcluiEnderecoButtonClick(ClickEvent event) {
//
//		for (PessoaEndereco e : enderecoList) {
//			if (e.equals(enderecoSelecionado)) {
//				enderecoList.remove(e);
//				break;
//			}
//		}
//		populaEnderecoFTable(enderecoList);
//
//	}

	@UiHandler("salvarEditButton")
	void onSalvarEditButtonClick(ClickEvent event) {
		if (checaCampoEmBrancoEnderecoView()) {
			PessoaEndereco pe = new PessoaEndereco();
			pe = pegaEnderecoView();
			if (indiceEnderecoSelecionado < 0) {
				// --- Novo Endereco
				enderecoList.add(pe);
			} else {
				// --- Endereco editado
				enderecoList.set(indiceEnderecoSelecionado, pe);
			}

			/* Se o Novo/editafo for o novo principal, rodo o list e desmarco o 
			 * principal de algum outro que esteja marcado
			 */
			if (pe.getPrincipal()){
				for (PessoaEndereco e : enderecoList) {
					if ( !e.equals(pe)){
						e.setPrincipal(false);
					}
				}
			}
			
			populaEnderecoTabela(enderecoList);
			dlg.hide();
		}
	}

	@UiHandler("cancelaEditButton")
	void onCancelaEditButtonClick(ClickEvent event) {
		dlg.hide();
	}

	private void openDlg(Widget w, String titulo) {
		showMessage(msgEditLabel, "", false);
		dlg.setGlassEnabled(true); // -- Deixa o fundo desabilitado fosco
		dlg.setModal(false);
		dlg.setText(titulo);
		w.setVisible(true);
		dlg.setWidget(w);
		dlg.center();
		dlg.show();
	}

	private void showMessage(Label caixa, String msg, Boolean exibe) {
		caixa.setVisible(exibe);
		if (exibe) {
			caixa.setText(msg);
		}
	}

	private void editaEndereco(final PessoaEndereco pessoaEndereco) {
		
		limpaEnderecoView();
		populaEnderecoView(pessoaEndereco);
		openDlg(editEnderecoPanel, "Editor de Endereço");

		
	}
	
	private void excluiEndereco(PessoaEndereco enderecoEditado) {
		this.enderecoList.remove(enderecoEditado);
		populaEnderecoTabela(this.enderecoList);
	}

	private void populaEnderecoTabela(List<PessoaEndereco> enderecoList) {
		enderecoDGrid.setRowData(enderecoList);
	}


	/*
	 * Views das Dlgs -- Endereco
	 */
	private void limpaEnderecoView() {
		tipoEnderecoLBox.setValue(null);
		principalCBox.setValue(false);
		enderecoView.limpaEnderecoView();
	}

	private void populaEnderecoView(final PessoaEndereco e) {
		if (e != null) {
			tipoEnderecoLBox.setValue(e.getTipoEndereco());
			principalCBox.setValue(e.getPrincipal());
			enderecoView.setAll(
					e.getEndereco().getCep(), 
					e.getEndereco().getPais(), 
					e.getEndereco().getEstado(), 
					e.getEndereco().getCidade(), 
					e.getEndereco().getTipoLogradouro(), 
					e.getEndereco().getLogradouro(), 
					e.getEndereco().getNumero(), 
					e.getEndereco().getComplemento(), 
					e.getEndereco().getBairro()
			);
		}
	}

	private PessoaEndereco pegaEnderecoView() {
		PessoaEndereco pe = new PessoaEndereco();

		pe.setTipoEndereco(tipoEnderecoLBox.getValue());
		pe.setPrincipal(principalCBox.getValue());

		Endereco e = new Endereco();
		e.setCep(enderecoView.getCep());
		e.setPais(enderecoView.getPais());
		e.setEstado(enderecoView.getEstado());
		e.setCidade(enderecoView.getCidade());
		e.setTipoLogradouro(enderecoView.getTipoLogradouro());
		e.setLogradouro(enderecoView.getLogradouro());
		e.setNumero(enderecoView.getNumero());
		e.setComplemento(enderecoView.getComplemento());
		e.setBairro(enderecoView.getBairro());

		pe.setEndereco(e);
		return pe;
	}

	private Boolean checaCampoEmBrancoEnderecoView() {
		if (tipoEnderecoLBox.getValue()==null ) {
			showMessage(msgEditLabel, "Campo Tipo de Endereço esta em branco", true);
			return false;
		}
		if ("".equals(enderecoView.getCep())) {
			showMessage(msgEditLabel, "Campo Cep esta em branco", true);
			return false;
		}
		if ("".equals(enderecoView.getPaisItem())) {
			showMessage(msgEditLabel, "Campo Pais esta em branco", true);
			return false;
		} else {
			if ("BRASIL".equals(enderecoView.getPaisItem())){
				if ("".equals(enderecoView.getEstadoItem())) {
					showMessage(msgEditLabel, "Campo Estado esta em branco", true);
					return false;
				}				
				if ("".equals(enderecoView.getCidadeItem())) {
					showMessage(msgEditLabel, "Campo Cidade esta em branco", true);
					return false;
				}				
			}
		}
		if ("".equals(enderecoView.getTipoLogradouroItem())) {
			showMessage(msgEditLabel, "Campo Tipo Logradouro esta em branco", true);
			return false;
		}				
		if ("".equals(enderecoView.getLogradouro())) {
			showMessage(msgEditLabel, "Campo Logradouro em branco", true);
			return false;
		}

		return true;
	}


}
